import React from 'react'
import _ from 'underscore'
import View from 'lib/View.jsx'
import TraceScope from './TraceScope.es6'
import Layout from '../common/layout.jsx'
import DefaultLoadingElement from 'lib/util/defaultLoadingElement.jsx'
import DefaultNoDataElement from 'lib/util/defaultNoDataElement.jsx'
import Card from 'lib/components/card.jsx'
import CardSpec from '../common/CardSpec.jsx'
import Tab from 'lib/components/tab.jsx'
import ChartWidget from 'lib/components/ChartWidget.jsx'
import GridWidget from 'lib/components/GridWidget.jsx'
import format from 'lib/util/format'
import { imsiColsNew } from '../imsisearch/imsiCrashCols.jsx'
import tips from '../common/indicator-tips.jsx'

function start_with(object, target) {

  let result = false;

  if (_.isArray(object) && object.length > 0) {
    let length = target.length;
    _.forEach(object, function (item) {
      if (item.substr(0, length) === target ||
          target.substr(0, item.length) === item) {
        return result = true;
      }
    });
  } else if (_.isString(object)){
    result = new RegExp('^' + target).test(object);
  }

  return result;
}

class IndexInput extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      currentOffset: props.value
    }; // state
  } // constructor

  componentWillReceiveProps(nextProps) {
    this.setState({
      currentOffset: nextProps.value
    });
  } // componentWillReceiveProps

  changeHandler({ target: { value } }) {
    if (value === '') {
      this.setState({ currentOffset: '' });
      return;
    }

    if (_.isFinite(value)) {
      let currentOffset = parseInt(value);
      if (currentOffset <= 0 || currentOffset > this.props.maxValue) {
        return;
      }

      this.setState({ currentOffset });
    }
  } // indexChangeHandler

  fireSearchHandler({ keyCode, altKey, ctrlKey, metaKey, shiftKey }) {
    if (!altKey && !ctrlKey && !metaKey && !shiftKey && keyCode === 13) {
      let { currentOffset } = this.state;
      if (currentOffset === '') {
        return;
      }

      this.props.onChange(parseInt(this.state.currentOffset));
    }
  } //fireSearchHandler

  resetValueHandler() {
    if (this.state.currentOffset === '') {
      this.setState({ currentOffset: this.props.value });
    }
  } // resetValueHandler

  render() {
    return (
      <input
        type="text"
        className="input-count"
        data-tip="输入完成后回车确认查询"
        onChange={ this.changeHandler.bind(this) }
        onKeyUp={ this.fireSearchHandler.bind(this) }
        onBlur={ this.resetValueHandler.bind(this) }
        value={ this.state.currentOffset } />
    );
  } // render
}

IndexInput.defaultProps = {
  value: 0,
  maxValue: 1000
}

class CrashTrack extends React.Component {

  constructor(props, context) {
    super(props, context);

    this.state = {
      text: this.props.text,
      currentLength: this.props.text.length
    }

    this.setOverflow = this.setOverflow.bind(this);
  }

  componentDidMount() {
    let main = this.refs.main;
    let link = this.refs.link;

    this.setOverflow(main, link);
  }

  setOverflow(main, link) {
    if (main.offsetWidth - 20 < link.offsetWidth) {
      let len = this.state.currentLength - 1;
      if (len > 0) {
        this.setState({
          text: this.props.text.substring(0, len) + '...',
          currentLength: len
        }, ()=>{
          this.setOverflow(main, link);
        });
      }
    }
  }

  render() {
    return (
      <li>
        <div ref="main" className="case" style={{wordBreak:'keep-all'}}>
          <strong>
            <a
              ref="link"
              style={{whiteSpace: 'nowrap'}}
              href={this.props.href}
              title={this.props.text}>
              {this.state.text}
            </a>
          </strong>
          <span>{this.props.timestampMs}</span>
        </div>
        {
          this.props.continue?( <i className="iconfont">&#xe613;</i>):null
        }
      </li>
    )
  }
}

CrashTrack.defaultProps = {
  continue: true
}

CrashTrack.propTypes = {
  // a.href
  href: React.PropTypes.string.isRequired,
  // a.innerText and a.title
  text: React.PropTypes.string.isRequired,
  // timestamp for millisecond
  timestampMs: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]),
  // add next arrow? default is true
  continue: React.PropTypes.bool
}

export default class TraceView extends View{
  toggleState(key){
    this.scope.toggleState(key)
  }
  onSwitch(index){
    if(index===1){
      this.scope.showDetail()
    }else{
      this.scope.showIMSI()
    }
  }

  fireSearchHandler(offset) {
    this.scope.showDetail.call(this.scope, offset - 1);
  } //fireSearchHandler

  renderLoading(){
    return (
      <div className="widget-content">
        <DefaultLoadingElement />
      </div>
    )
  }
  renderDetail(trace){
    var _this = this
    return (
      <div className="widget-content">
        <div className="pure-g">
          <div className="pure-u-1">
            <div className="box">
              <Card>
                <table className="text-detail">
                  <tbody>
                    <tr key={1}>
                      <th>应用版本：</th>
                      <td>
                        {trace.appVersion}
                      </td>
                      <th>同类崩溃：</th>
                      <td>
                        {trace.count}
                      </td>
                      <th>影响设备：</th>
                      <td>
                        { this.state.affectedUser < 0 ? '' : this.state.affectedUser}
                      </td>
                    </tr>
                    <tr key={2}>
                      <th>最后发生时间：</th>
                      <td>
                        {format.stampToTime(trace.lastTime)+' - '+format.duration(trace.lastTime)}
                      </td>
                    </tr>
                    <tr key={3}>
                      <th>状态：</th>
                      <td>
                        <a href="javascript:;" onClick={this.toggleState.bind(this,'fix')}>
                        {trace.fixed?'已解决':'未解决'}
                        </a>
                      </td>
                      <th>优先级：</th>
                      <td>
                        <a href="javascript:;" onClick={this.toggleState.bind(this,'follow')}>
                        {trace.follow?'高':'低'}
                        </a>
                      </td>
                      <th>是否隐藏：</th>
                      <td>
                        <a href="javascript:;" onClick={this.toggleState.bind(this,'ignores')}>
                        {trace.ignores?'是':'否'}
                        </a>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </Card>
            </div>
          </div>
        </div>
        <div className="pure-g">
          <div className="pure-u-1 pure-u-lg-1-3">
            <div className="box">
              <Card title="崩溃次数">
                <ChartWidget store={this.state.chart}/>
              </Card>
            </div>
          </div>
          <div className="pure-u-1 pure-u-lg-1-3">
            <div className="box">
              <Card title="影响设备 Top 5">
                <ChartWidget store={this.state.pie0} chartType="pie" chartSettings={this.state.pieChartSettings} />
              </Card>
            </div>
          </div>
          <div className="pure-u-1 pure-u-lg-1-3">
            <div className="box">
              <Card title="影响操作系统版本 Top 5">
                <ChartWidget store={this.state.pie1} chartType="pie" chartSettings={this.state.pieChartSettings} />
              </Card>
            </div>
          </div>
        </div>
        <div className="pure-g">
          <div className="pure-u-1">
            <div className="box">
              <Tab onAfterChange={this.onSwitch.bind(this)}>
                <Tab.Panel title="崩溃详情" key="detail">
                  {
                    !this.state.detail
                      ? (
                          <Card>
                            <DefaultLoadingElement style={{color:'black'}} />
                          </Card>
                      ) : null
                  }
                  {
                    this.state.detail ? (
                      <Card>
                        <div className="trace-cross-title">
                          <span
                            className="previous first"
                            data-tip="第一个"
                            onClick={this.scope.showDetail.bind(this.scope, 0)}>
                            <a href="javascript:;" className="iconfont">&#xe6f0;</a>
                          </span>
                          <span
                            className="previous"
                            data-tip="前一个"
                            onClick={this.scope.showDetail.bind(this.scope,this.scope.traceOffset - 1)}>
                            <a href="javascript:;" className="iconfont">&#xe658;</a>
                          </span>
                          <h4>
                            <p>
                              {'第 '}
                              <IndexInput
                                value={ this.scope.traceOffset + 1 }
                                maxValue={ this.state.trace.count }
                                onChange={ this.fireSearchHandler.bind(this) } />
                              {`/ ${ this.state.trace.count } 个同类崩溃`}
                            </p>
                            <p>{'发生时间：'+format.stampToTime(this.state.detail.timestamp)}</p>
                          </h4>
                          <span
                            className="next"
                            data-tip="后一个"
                            onClick={this.scope.showDetail.bind(this.scope,this.scope.traceOffset + 1)}>
                            <a href="javascript:;" className="iconfont">&#xe659;</a>
                          </span>
                          <span
                            className="next last"
                            data-tip="最后一个"
                            onClick={this.scope.showDetail.bind(this.scope, this.state.trace.count - 1)}>
                            <a href="javascript:;" className="iconfont">&#xe6f1;</a>
                          </span>
                        </div>
                      </Card>
                    ):null
                  }
                  {
                    this.state.detail && this.state.crashDetailProcessing ? (
                      <Card>
                        <DefaultLoadingElement style={{ color: 'black' }} />
                      </Card>
                    ) : null
                  }
                  {
                    this.state.detail && !this.state.crashDetailProcessing ? (
                      <Card>
                        <div className="pure-g">
                          <div className="pure-u-1">
                          代码定位：
                          {
                            _.isString(this.state.detail.name.symbol)
                              ? this.state.detail.name.symbol
                              : (
                                <span>
                                  {this.state.detail.name.symbol.methodName + ' '}
                                  <span style={{color:'#d2d2d2'}}>@</span>
                                  {' ' + this.state.detail.name.symbol.rowNumber + ' '}
                                  <span style={{color:'#d2d2d2'}}>in</span>
                                  {' ' + this.state.detail.name.symbol.fileName}
                                </span>
                              )
                          }
                          </div>
                          {
                            this.state.detail.exceptionReason?(
                              <div className="pure-u-1">
                              崩溃原因：
                              {this.state.detail.exceptionReason}
                              </div>
                            ):null
                          }
                          {
                            this.state.detail.exceptionType?(
                              <div className="pure-u-1 pure-u-lg-1-2">
                              崩溃类型：
                              {this.state.detail.exceptionType}
                              </div>
                            ):null
                          }
                          <div className="pure-u-1 pure-u-lg-1-2">
                          APP版本：
                          {this.state.detail.appVersionName}
                          </div>
                          <div className="pure-u-1 pure-u-lg-1-2">
                          设备信息：
                          {this.state.detail.manufacturerName + ' ' + this.state.detail.modelName}
                          </div>
                          <div className="pure-u-1 pure-u-lg-1-2">
                          操作系统：
                          {this.state.detail.osName + ' ' + this.state.detail.osVersionName}
                          </div>
                          <div className="pure-u-1 pure-u-lg-1-2">
                          内存占用：
                          {BlueWare.isIOS?format.dataSize(this.state.detail.memUsed):(this.state.detail.deviceInfo.memoryUsage + 'MB')}
                          </div>
                          {
                            BlueWare.isAndroid?(
                              <div className="pure-u-1 pure-u-lg-1-2">
                              联网方式：
                              {this.state.detail.deviceInfo.networkStatus}
                              </div>
                            ):null
                          }
                          {
                            BlueWare.isAndroid && (this.state.detail.deviceInfo.diskAvailable.length > 1) ? (
                              <div className="pure-u-1 pure-u-lg-1-2">
                              内部可用：
                              {format.dataSize(this.state.detail.deviceInfo.diskAvailable[0])}
                              ，外部可用：
                              {format.dataSize(this.state.detail.deviceInfo.diskAvailable[1])}
                              </div>
                            ):null
                          }
                          {
                            BlueWare.isAndroid && (this.state.detail.deviceInfo.diskAvailable.length === 1) ? (
                              <div className="pure-u-1 pure-u-lg-1-2">
                              内部可用：
                              {format.dataSize(this.state.detail.deviceInfo.diskAvailable[0])}
                              </div>
                            ):null
                          }
                          {
                            this.state.detail.agentVersion?(
                              <div className="pure-u-1 pure-u-lg-1-2">
                              Agent版本号：
                              {this.state.detail.agentVersion}
                              </div>
                            ):null
                          }
                          {
                            BlueWare.isAndroid?(
                              <div className="pure-u-1 pure-u-lg-1-2">
                              屏幕朝向：
                              {this.state.detail.deviceInfo.orientation===1?'竖屏':'横屏'}
                              </div>
                            ):null
                          }
                          {
                            BlueWare.isAndroid&&this.state.detail.extraData.datas.rooted?(
                              <div className="pure-u-1 pure-u-lg-1-2">
                              是否root：
                              {this.state.detail.extraData.datas.rooted==='1'?'是':'否'}
                              </div>
                            ):null
                          }
                        </div>
                      </Card>
                    ):null
                  }
                  {
                    this.state.detail  && !this.state.crashDetailProcessing && this.state.detail.cause ? (
                      <Card title="错误信息">
                        {this.state.detail.cause}
                      </Card>
                    ):null
                  }
                  {
                    BlueWare.isAndroid && this.state.detail && !this.state.crashDetailProcessing && this.state.detail.runningApps ? (
                      <CardSpec title="后台 App" useToggle={true}>
                        <table className="table table-striped">
                          <tbody>
                            <tr>
                              <th>
                                PID
                              </th>
                              <th>
                                名称
                              </th>
                              <th>
                                程序包名
                              </th>
                              <th>
                                内存占用
                              </th>
                            </tr>
                            {
                              this.state.detail.runningApps.map(function(app,i){
                                return (
                                  <tr key={i}>
                                    <td>{app.pid}</td>
                                    <td>{app.name}</td>
                                    <td>
                                      {
                                        app.packages.map(function(p,index){
                                          var tu = [<br key={index} />,p]
                                          if(!index){
                                            tu.shift()
                                          }
                                          return tu
                                        })
                                      }
                                    </td>
                                    <td>{format.dataSize(app.mem)}</td>
                                  </tr>
                                )
                              })
                            }
                          </tbody>
                        </table>
                      </CardSpec>
                    ):null
                  }
                  {
                    this.state.detail && !this.state.crashDetailProcessing && this.state.detail.activityHistory ? (
                      <Card title="崩溃轨迹">
                        {
                          this.state.detail?(
                            <div className="interaction">
                              <ul className="clearfix">
                                <li>
                                  <div className="case">
                                    <strong><a>Session Start</a></strong>
                                  </div>
                                  <i className="iconfont">&#xe613;</i>
                                </li>
                                {
                                  this.state.detail.activityHistory.map(function(a,i,arr){
                                    return (
                                      <CrashTrack
                                        key={ i }
                                        href={_this.scope.genActivityUrl(a)}
                                        text={a.name}
                                        timestampMs={i===arr.length-1?format.stampToTime(this.timestampMs):format.qDuration(a.timestampMs,this.timestampMs)}
                                        continue={i!==arr.length-1} />
                                    )
                                  },_(this.state.detail.activityHistory).last())
                                }
                              </ul>
                            </div>
                          ):null
                        }
                      </Card>
                    ):null
                  }
                  {
                    this.state.detail && !this.state.crashDetailProcessing ? (
                      <Card>
                        <div className="crash-threads">
                          <table className="table table-striped">
                            {
                              this.state.detail.threads.map(function(thread){
                                return [
                                  <thead key={Math.random()}>
                                    <tr>
                                      <th colSpan={BlueWare.isIOS?4:2}>
                                        {BlueWare.isIOS?thread.name:'Thread - ' + thread.threadName}
                                      </th>
                                    </tr>
                                  </thead>
                                  ,
                                  <tbody key={Math.random()}>
                                    {
                                      BlueWare.isAndroid?(
                                      <tr>
                                        <th>
                                          包名
                                        </th>
                                        <th>
                                          详细信息
                                        </th>
                                      </tr>
                                      ):null
                                    }
                                    {
                                      BlueWare.isIOS?(
                                        thread.entries?thread.entries.map(function(entry,i){
                                          var styleObj = {}
                                          if(entry.imageName===this.state.detail.userImage){
                                            styleObj.color = '#FF0000'
                                          }
                                          return (
                                            <tr style={styleObj} key={i}>
                                              <td style={{width:40}}>{i}</td>
                                              <td style={{width:200}}>{entry.imageName}</td>
                                              <td style={{width:200}}>{entry.rawAddress}</td>
                                              <td>{entry.symbol}</td>
                                            </tr>
                                          )
                                        },this):null
                                      ):(
                                        thread.stack.map(function(stack, index){
                                          var styleObj = {}
                                          if(thread.crashed&&!!(_.findWhere([this.state.detail.name],_.pick(stack,'fileName','className','methodName')))){
                                            styleObj.color = '#FF0000';
                                            styleObj.fontWeight = 'bold';
                                          }

                                          let packageName = stack.className.substring(0, _.lastIndexOf(stack.className, '.'));

                                          if ((this.state.detail.validPackageList || '').indexOf(packageName) !== -1
                                              || start_with(this.state.detail.validPackageList, packageName + '.')) {
                                            styleObj.color = '#FF0000';
                                          }
                                          return (
                                            <tr style={styleObj} key={index}>
                                              <td>
                                                { packageName }
                                              </td>
                                              <td>
                                                {stack.fileName + ' line ' + stack.lineNumber + ' in ' +stack.className + '.' + stack.methodName + '()'}
                                              </td>
                                            </tr>
                                          )
                                        },this)
                                      )
                                    }
                                  </tbody>
                                ]
                              },this)
                            }
                          </table>
                        </div>
                      </Card>
                    ):null
                  }
                </Tab.Panel>
                <Tab.Panel title="影响用户" key="imsi">
                  <div>
                    <Card>
                      <GridWidget
                        store={this.state.imsiGrid}
                        cols={imsiColsNew}
                        nodataElement={"暂无影响用户信息"}
                        loadingElement={ <DefaultLoadingElement style={{color:'black'}} /> } />
                    </Card>
                  </div>
                </Tab.Panel>
              </Tab>
            </div>
          </div>
        </div>
      </div>
    )
  }
  render(){
    return (
      <div className="pure-g">
        <div className="pure-u-1">
          <div className="box">
            <div className="widget-float">
              <div className="widget-title">
                <a className="close iconfont" href="javascript:;" onClick={ this.props.history.goBack }>&#xe638;</a>
                {this.state.trace&&this.state.trace.name?(<h4 className="text-overflow" style={{ maxWidth: 300 }}>{this.state.trace.name.reason}</h4>):null}
              </div>
              {this.state.trace?(
                this.renderDetail(this.state.trace)
              ):(this.state.trace!==null?(
                <div className="widget-content">
                  <DefaultNoDataElement />
                </div>
              ):this.renderLoading())}
            </div>
          </div>
        </div>
      </div>
    )
  }
}
TraceView.defaultProps = {
  Scope:TraceScope
}
